namespace AnalyStock.DataManage;

/// <summary>
///     下载在线数据通用Template
/// </summary>
/// <typeparam name="T"></typeparam>
internal interface IDownDataTemplate<T>
{
    Task<IList<T>> DownloadOnlineAsync(params string[] args);
}

internal class DownDataTemplate<T> : IDownDataTemplate<T> where T : class, new()
{
    public virtual async Task<IList<T>> DownloadOnlineAsync(params string[] args)
    {
        await Task.Delay(5).ConfigureAwait(false);
        return new List<T>();
    }
}

internal static class DataTableToCollection
{
    public static IList<T> ConvertTableToList<T>
        (this DataTable dtResult) where T : class, new()
    {
        List<T> lstT = new();
        foreach (DataRow dr in dtResult.Rows)
        {
            T t = new();
            foreach (var pi in typeof(T).GetProperties())
            {
                var piName = pi.Name.ToLower();
                if (dtResult.Columns.Contains(piName)
                    && dr.Field<object>(piName) is string fieldValue)
                {
                    pi.SetValue(t, Convert.ChangeType(fieldValue, pi.PropertyType));
                }
            }            
            lstT.Add(t);
        }
        return lstT;
    }
}


#region
/// <summary>
///     下载股票基本数据集合，参数args:null,null,null
/// </summary>
internal class DownloadOnline_StockBasic : DownDataTemplate<StockBasic>
{
    public override async Task<IList<StockBasic>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new()
        {
            { "list_status", "L" }
        };
        var fields = "ts_code,symbol,name,area,industry,market,list_date,cnspell,exchange";
        using var dtResulte = await UtilityOfTuShare
                                        .GetTradeDataAsync("stock_basic", paramKey, fields)
                                        .ConfigureAwait(false);
        return dtResulte.ConvertTableToList<StockBasic>();
    }
}

/// <summary>
///  参数args:   null, null,tradedate
/// </summary>
internal class DownloadOnline_BakDaily : DownDataTemplate<BakDaily>
{
    public override async Task<IList<BakDaily>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new()
        {
            { "trade_date", args[0] }
        };
        using var dtResulte =
            await UtilityOfTuShare.GetTradeDataAsync("bak_daily", paramKey)
                                  .ConfigureAwait(false);
        return dtResulte.ConvertTableToList<BakDaily>();
    }
}

/// <summary>
///  参数args:   startdate, enddate, null
/// </summary>
internal class DownloadOnline_TradeCalendar : DownDataTemplate<TradeCalendar>
{
    public override async Task<IList<TradeCalendar>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new()
        {
            { "start_date", args[0] },
            { "end_date", args[1] },
            { "exchange", "SSE" }, //市场             
            { "is_open", "1" }
        };
        using var dtResulte =
            await UtilityOfTuShare.GetTradeDataAsync("trade_cal", paramKey)
                                  .ConfigureAwait(false);
        return dtResulte.ConvertTableToList<TradeCalendar>();
    }
}

/// <summary>
///  参数args:   null, null, tradedate 下载当日全部交易数据
///  参数args:   ts_code, startdate, enddate 下载单个股票数据
/// </summary>
internal class DownloadOnline_Daily : DownDataTemplate<Daily>
{
    public override async Task<IList<Daily>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new();
        if (args.Length > 1)
        {
            paramKey.Add("ts_code", args[0]);
            paramKey.Add("start_date", args[1]);
            paramKey.Add("end_date", args[2]);
        }
        else
        {
            paramKey.Add("trade_date", args[0]);
        }

        using var dtDaily = await UtilityOfTuShare.GetTradeDataAsync("daily", paramKey)
                                                  .ConfigureAwait(false);
        using var dtAdjFactor = await UtilityOfTuShare.GetTradeDataAsync("adj_factor", paramKey)
                                                      .ConfigureAwait(false);
        IEnumerable<Daily> mergeBakDailes;
        if (args.Length > 1)
        {
            //下载当日全部交易数据
            mergeBakDailes = from trdata in dtDaily.ConvertTableToList<Daily>()
                             join adjdata in dtAdjFactor.ConvertTableToList<AdjFactor>()
                                 on trdata.Trade_date equals adjdata.Trade_date
                             orderby trdata.Trade_date
                             select new Daily
                             {
                                 Ts_code = trdata.Ts_code,
                                 Trade_date = trdata.Trade_date,
                                 Open = trdata.Open,
                                 High = trdata.High,
                                 Low = trdata.Low,
                                 Close = trdata.Close,
                                 Pre_close = trdata.Pre_close,
                                 Change = trdata.Change,
                                 Pct_chg = trdata.Pct_chg,
                                 Vol = trdata.Vol,
                                 Amount = trdata.Amount,
                                 Adj_factor = adjdata.Adj_factor
                             };
        }
        else
        {
            //下载单个股票期间交易数据
            mergeBakDailes = from trdata in dtDaily.ConvertTableToList<Daily>()
                             join adjdata in dtAdjFactor.ConvertTableToList<AdjFactor>()
                                 on trdata.Ts_code equals adjdata.Ts_code
                             orderby trdata.Ts_code
                             select new Daily
                             {
                                 Ts_code = trdata.Ts_code,
                                 Trade_date = trdata.Trade_date,
                                 Open = trdata.Open,
                                 High = trdata.High,
                                 Low = trdata.Low,
                                 Close = trdata.Close,
                                 Pre_close = trdata.Pre_close,
                                 Change = trdata.Change,
                                 Pct_chg = trdata.Pct_chg,
                                 Vol = trdata.Vol,
                                 Amount = trdata.Amount,
                                 Adj_factor = adjdata.Adj_factor
                             };
        }

        return mergeBakDailes.ToList();
    }
}

/// <summary>
///  参数args:   ts_code, startdate, enddate, fields 单个股票动态财务快报数据数据下载
/// </summary>
internal class DownloadOnline_DynamicFinancialIndex : DownDataTemplate<DynamicFinancialIndex>
{
    public override async Task<IList<DynamicFinancialIndex>> DownloadOnlineAsync(params string[] args)
    {
        Dictionary<string, string> paramKey = new()
        {
            {"ts_code", args[0]},
            { "start_date", args[1] },
            { "end_date", args[2] }
        };
        var fields = "ts_code,ann_date,end_date,eps,q_eps,bps,ocfps,or_yoy,op_yoy,ocf_yoy,q_sales_qoq,q_op_qoq,"
                    + "netprofit_margin,grossprofit_margin,roe,debt_to_assets,gross_margin,extra_item,non_op_profit,profit_dedt";
        using var dtResulte =
            await UtilityOfTuShare.GetTradeDataAsync("fina_indicator", paramKey, fields).ConfigureAwait(false);

        //这里取出来的数据存在重复记录
        return dtResulte.ConvertTableToList<DynamicFinancialIndex>().DistinctBy(n => n.End_date).ToList();
    }
}

/// <summary>
/// 腾讯当日交易数据
/// 参数args:    ts_code, null, null, null
/// </summary>
internal class DownloadOnline_DailyOfTencent : DownDataTemplate<DailyOfTencent>
{
    public override async Task<IList<DailyOfTencent>> DownloadOnlineAsync(params string[] args)
    {
        return new List<DailyOfTencent>
        {
            await UtilityOfTencent.GetTodayTradeData(args[0]).ConfigureAwait(false)
        };
    }
}

internal class DownloadOnline_MinuteOfTencent : DownDataTemplate<MinuteOfTencent>
{
    public override async Task<IList<MinuteOfTencent>> DownloadOnlineAsync(params string[] args)
    {
        return new List<MinuteOfTencent>
        {
            await UtilityOfTencent.GetMintueTradeData(args[0]).ConfigureAwait(false)
        };
    }
}

#endregion